Add wrappers for setting the WidgetClass.activate_signal field
authorEmmanuele Bassi <ebassi@gnome.org>
Fri, 4 Dec 2020 17:01:23 +0000 (17:01 +0000)
committerEmmanuele Bassi <ebassi@gnome.org>
Sat, 5 Dec 2020 01:04:18 +0000 (01:04 +0000)
Setting a field on a class structure is not always an easy task from
languages other than C. While bindings can provide access to the class
pointer, twiddling the fields in the class structure can be awkward.
Additionally, signal ids are not always readily available.

We can paper over the direct access to the class structure, as well as
the "signal name to id" mapping with a simple couple of setter
functions.

docs/reference/gtk/gtk4-sections.txt
gtk/gtkwidget.c
gtk/gtkwidget.h

index 77316a4fb6dfd5314c6a1306da35ce698c984e8c..66eae4da6a1704f9ca1a6eadceb73fde918576e8 100644 (file)
@@ -4366,6 +4366,8 @@ gtk_widget_class_add_binding_signal
 gtk_widget_class_add_binding_action
 gtk_widget_class_set_layout_manager_type
 gtk_widget_class_get_layout_manager_type
+gtk_widget_class_set_activate_signal
+gtk_widget_class_set_activate_signal_from_name
 gtk_widget_activate
 gtk_widget_is_focus
 gtk_widget_grab_focus
index ab9de00cd23d4a4cbb89496f122fc94e37e491ed..1ae404c425fd0d9b54b2c50a7725bcc2ed3ef61b 100644 (file)
@@ -4296,11 +4296,22 @@ gtk_widget_mnemonic_activate (GtkWidget *widget,
   return handled;
 }
 
+static gboolean
+gtk_widget_can_activate (GtkWidget *self)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (self);
+
+  if (widget_class->activate_signal != 0)
+    return TRUE;
+
+  return FALSE;
+}
+
 static gboolean
 gtk_widget_real_mnemonic_activate (GtkWidget *widget,
                                    gboolean   group_cycling)
 {
-  if (!group_cycling && GTK_WIDGET_GET_CLASS (widget)->activate_signal)
+  if (!group_cycling && gtk_widget_can_activate (widget))
     gtk_widget_activate (widget);
   else if (gtk_widget_get_can_focus (widget))
     return gtk_widget_grab_focus (widget);
@@ -4562,6 +4573,61 @@ gtk_widget_event (GtkWidget *widget,
   return return_val;
 }
 
+/**
+ * gtk_widget_class_set_activate_signal:
+ * @widget_class: a #GtkWidgetClass
+ * @signal_id: the id for the activate signal
+ *
+ * Sets the #GtkWidgetClass.activate_signal field with the
+ * given @signal_id; the signal will be emitted when calling
+ * gtk_widget_activate().
+ *
+ * The @signal_id must have been registered with g_signal_new()
+ * or g_signal_newv() before calling this function.
+ */
+void
+gtk_widget_class_set_activate_signal (GtkWidgetClass *widget_class,
+                                      guint           signal_id)
+{
+  g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
+  g_return_if_fail (signal_id != 0);
+
+  widget_class->activate_signal = signal_id;
+}
+
+/**
+ * gtk_widget_class_set_activate_signal_from_name:
+ * @widget_class: a #GtkWidgetClass
+ * @signal_name: the name of the activate signal of @widget_type
+ *
+ * Sets the #GtkWidgetClass.activate_signal field with the signal id for
+ * the given @signal_name; the signal will be emitted when calling
+ * gtk_widget_activate().
+ *
+ * The @signal_name of @widget_type must have been registered with
+ * g_signal_new() or g_signal_newv() before calling this function.
+ */
+void
+gtk_widget_class_set_activate_signal_from_name (GtkWidgetClass *widget_class,
+                                                const char     *signal_name)
+{
+  guint signal_id;
+
+  g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
+  g_return_if_fail (signal_name != NULL);
+
+  signal_id = g_signal_lookup (signal_name, G_TYPE_FROM_CLASS (widget_class));
+  if (signal_id == 0)
+    {
+      g_critical ("Widget type “%s” does not have a “%s” signal",
+                  G_OBJECT_CLASS_NAME (widget_class),
+                  signal_name);
+      return;
+    }
+
+  widget_class->activate_signal = signal_id;
+}
+
 /**
  * gtk_widget_activate:
  * @widget: a #GtkWidget that’s activatable
@@ -4578,7 +4644,7 @@ gtk_widget_activate (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  if (GTK_WIDGET_GET_CLASS (widget)->activate_signal)
+  if (gtk_widget_can_activate (widget))
     {
       /* FIXME: we should eventually check the signals signature here */
       g_signal_emit (widget, GTK_WIDGET_GET_CLASS (widget)->activate_signal, 0);
index 61379b558e0aa69873da81341835552d9058d252..8aa2403ac959ac5d69043f5b8732e6c663adb41a 100644 (file)
@@ -364,6 +364,13 @@ GDK_AVAILABLE_IN_ALL
 void       gtk_widget_class_add_shortcut  (GtkWidgetClass      *widget_class,
                                            GtkShortcut         *shortcut);
 
+GDK_AVAILABLE_IN_ALL
+void       gtk_widget_class_set_activate_signal                 (GtkWidgetClass *widget_class,
+                                                                 guint           signal_id);
+GDK_AVAILABLE_IN_ALL
+void       gtk_widget_class_set_activate_signal_from_name       (GtkWidgetClass *widget_class,
+                                                                 const char     *signal_name);
+
 GDK_AVAILABLE_IN_ALL
 gboolean   gtk_widget_mnemonic_activate   (GtkWidget           *widget,
                                            gboolean             group_cycling);